﻿using System;
using Birkelund.QueryStrings.Tokens;
using NUnit.Framework;

namespace Birkelund.QueryStrings.Test
{
    public class StringTokenEncryptedTest
    {
        #region String Encrypted
        [Test]
        public void SetValue_String_Encrypted_Simple()
        {
            Uri initialUrl = new Uri(@"http://localhost/test/testFile.aspx");
            string expected = "http://localhost/test/testFile.aspx?a=XObhMaFBniE%3d";

            IQueryStringToken<string> a = new StringToken("a") { EncryptionAlgorithm = new DesEncryptionImpl() };

            IUriWriter writer = UriWriter.CreateFromUri(initialUrl);
            writer.SetToken(a, "myvalue");

            Assert.AreEqual(expected, writer.GenerateQueryAsString());
        }

        [Test]
        public void SetValue_String_Encrypted_WithUnencryptedValues()
        {
            Uri initialUrl = new Uri(@"http://localhost/test/testFile.aspx");
            string expected = "http://localhost/test/testFile.aspx?a=XObhMaFBniE%3d&b=5&c=zRe2s8eEU3Q%3d";

            IQueryStringToken<string> a = new StringToken("a") { EncryptionAlgorithm = new DesEncryptionImpl() };
            IQueryStringToken<int> b = new ValueTypeToken<int>("b");
            IQueryStringToken<int> c = new ValueTypeToken<int>("c") { EncryptionAlgorithm = new DesEncryptionImpl() };

            IUriWriter writer = UriWriter.CreateFromUri(initialUrl);
            writer.SetToken(a, "myvalue");
            writer.SetToken(b, 5);
            writer.SetToken(c, -7);

            Assert.AreEqual(expected, writer.GenerateQueryAsString(), "Test1");

            Uri generatedUri = writer.GenerateQueryAsUri();
            Assert.AreEqual("myvalue", a.ReadValue(generatedUri));
            Assert.AreEqual(5, b.ReadValue(generatedUri));
            Assert.AreEqual(-7, c.ReadValue(generatedUri));
        }

        [Test]
        public void SetValue_String_Encrypted_WithSpecialChars()
        {
            Uri initialUrl = new Uri(@"http://localhost/test/testFile.aspx");
            string expected = @"http://localhost/test/testFile.aspx?a=Dn37CQOgZp86FDB35SPGweiOYiWFLYztmAtMy7vwGM2Os3g5%2bAQQaxIegG3CWGop";
                                                                    
            IQueryStringToken<string> a = new StringToken("a") { EncryptionAlgorithm = new DesEncryptionImpl() };

            string initialValue = @"\æ &""?øå'%++´`=¨_~^ø.´`|Óʘʤﭿ";
            IUriWriter writer = UriWriter.CreateFromUri(initialUrl);
            writer.SetToken(a, initialValue);

            Console.Out.WriteLine(writer.GenerateQueryAsString());
            Assert.AreEqual(expected, writer.GenerateQueryAsString(), "Test1");

            Uri generatedUri = writer.GenerateQueryAsUri();
            Assert.AreEqual(initialValue, a.ReadValue(generatedUri), "Test2");

        }

        [Test]
        public void SetValue_String_Encrypted_Null()
        {
            Uri initialUrl = new Uri(@"http://localhost/test/testFile.aspx");
            string expected = new Uri(@"http://localhost/test/testFile.aspx?a=").ToString();

            IQueryStringToken<string> a = new StringToken("a") { EncryptionAlgorithm = new DesEncryptionImpl() };

            IUriWriter writer = UriWriter.CreateFromUri(initialUrl);
            writer.SetToken(a, null);

            Assert.AreEqual(expected, writer.GenerateQueryAsString());
        }

        [Test]
        public void ReadErrornousEncryptedValue()
        {
            Uri initialUrl = new Uri(@"http://localhost/test/testFile.aspx?a=INVALID");

            IQueryStringToken<string> a = new StringToken("a") { EncryptionAlgorithm = new DesEncryptionImpl() };

            TokenParserException ex = Assert.Throws<TokenParserException>(() => a.ReadValue(initialUrl));
            Assert.AreEqual(FailureReason.ParseError, ex.FailureArgs.Reason);
        }
        #endregion

    }
}
